Skip to content

feat(vault): async withdrawal queue for illiquid exits#13

Merged
jayeshy14 merged 1 commit into
mainfrom
feat/withdrawal-queue
May 31, 2026
Merged

feat(vault): async withdrawal queue for illiquid exits#13
jayeshy14 merged 1 commit into
mainfrom
feat/withdrawal-queue

Conversation

@jayeshy14
Copy link
Copy Markdown
Owner

Summary

Tier 3 — asynchronous withdrawal queue. Gives users an exit path when the vault lacks idle liquidity to satisfy a synchronous ERC-4626 withdraw/redeem (notably when capital sits in an illiquid strategy like Pendle PT before maturity). The requester escrows shares; a curator/keeper frees liquidity via rebalance, then fulfils the claim at the live share price.

Design

  • LibWithdrawQueue — namespaced storage (nextRequestId, requests, totalPendingShares).
  • Vault (native)requestWithdraw / cancelWithdraw / fulfillWithdraw. These are native (not on the facet) because only the native ERC-4626 surface can _transfer/_burn shares; a facet would need an approve-dance and lose the user's msg.sender. Mirrors the existing Lib-storage + native-enforcement + facet-readers pattern.
  • WithdrawQueueFacet — readers (nextWithdrawRequestId, pendingWithdrawShares, withdrawRequest).

Key choices

  • Escrow + price-at-fulfill, not lock-price-at-request: requests stay NAV-neutral and the requester keeps full exposure until paid, so the queue can't lock in a stale price at the stayers' expense.
  • fulfillWithdraw is curator-gated (LibRoles), nonReentrant, honors the circuit breaker, accrues fees first, reverts InsufficientIdleLiquidity when idle is short (CEI: effects + burn before transfer).
  • Composes with the merged guardrails: the escrow transfer respects the share-lock; synchronous withdraw/redeem are unchanged (only illiquid exits queue).

Verification

  • forge build clean, forge fmt clean.
  • forge test --no-match-path 'test/integration/*'158 passed, 0 failed (+12 new, incl. test_IlliquidExit_FreedByRebalanceThenFulfilled).
  • diamond-detect → no storage collisions, 10 namespaced regions each on its own slot.

@jayeshy14 jayeshy14 merged commit f89d491 into main May 31, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant